/**
 * 
 */
package org.hotpotmaterial.codegenn2.service.impl;

import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.hotpotmaterial.codegenn2.common.HmCodeGenConstants;
import org.hotpotmaterial.codegenn2.common.enums.PersistEnum;
import org.hotpotmaterial.codegenn2.dao.ProjectPluginMapper;
import org.hotpotmaterial.codegenn2.dao.ProjectPluginPropertyMapper;
import org.hotpotmaterial.codegenn2.entity.HmteamAccount;
import org.hotpotmaterial.codegenn2.entity.ProjectPlugin;
import org.hotpotmaterial.codegenn2.entity.ProjectPluginExample;
import org.hotpotmaterial.codegenn2.entity.ProjectPluginProperty;
import org.hotpotmaterial.codegenn2.entity.ProjectPluginPropertyExample;
import org.hotpotmaterial.codegenn2.service.IProjectPluginService;
import org.hotpotmaterial.codegenn2.template.CodeGenerateExcutor;
import org.hotpotmaterial.codegenn2.utils.AESUtil;
import org.hotpotmaterial.codegenn2.utils.RequestUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.collect.Maps;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;

/**
 * @author causer
 *
 */
@Service
public class ProjectPluginServiceImpl implements IProjectPluginService {

	@Autowired
	private ProjectPluginMapper projectPluginMapper;

	@Autowired
	private ProjectPluginPropertyMapper projectPluginPropertyMapper;

	@Autowired
	private ApplicationContext applicationContext;

	@Override
	public List<ProjectPlugin> findProjectPlugins(Long projectModuleId) {
		ProjectPluginExample example = new ProjectPluginExample();
		example.createCriteria().andModuleIdEqualTo(projectModuleId)
				.andIsDeletedEqualTo(HmCodeGenConstants.DATA_IS_VALID);
		return projectPluginMapper.selectByExample(example);
	}

	@Override
	@Transactional
	public int insertProjectPlugin(ProjectPlugin record) {
		// 默认字段
		setDefaultColumns(record, PersistEnum.insert);
		projectPluginMapper.insertSelective(record);
		// 保存属性
		this.saveProjectPluginProperties(record.getId(), record.getPluginProperties());
		return 0;
	}
	
	@Override
	public ProjectPlugin findById(Long id) {
		ProjectPlugin record = projectPluginMapper.selectByPrimaryKey(id);
		// 获取属性
		record.setPluginProperties(this.getProjectPluginProperties(id));
		return record;
	}

	@Override
	@Transactional
	public int updateProjectPlugin(Long id, ProjectPlugin record) {
		// 默认字段
		record.setId(id);
		setDefaultColumns(record, PersistEnum.update);
		projectPluginMapper.updateByPrimaryKeySelective(record);
		// 保存属性
		this.saveProjectPluginProperties(record.getId(), record.getPluginProperties());
		return 0;
	}

	@Override
	@Transactional
	public int delProjectPlugin(Long id) {
		ProjectPlugin record = projectPluginMapper.selectByPrimaryKey(id);
		if (record != null) {
			setDefaultColumns(record, PersistEnum.delete);
			return projectPluginMapper.updateByPrimaryKeySelective(record);
		}
		return 0;
	}

	@Override
	public String getFileContent(String fileName) {
		return FileUtil.readUtf8String(fileName);
	}

	@Override
	public String generateFileTree(Long id, Map<String, String> password) {
		// 获取登录信息
		HmteamAccount loginUser = RequestUtil.getAccountInfo();
		ProjectPlugin record = projectPluginMapper.selectByPrimaryKey(id);
		if (record != null) {
			// 获取插件名称
			String pluginName = record.getPluginName();
			// 获取bean
			CodeGenerateExcutor excutor = (CodeGenerateExcutor) applicationContext.getBean(pluginName);
			// 模板生成文件属性值
			Map<String, String> renderParams = Maps.newHashMap();
			// 获取属性值
			ProjectPluginPropertyExample example = new ProjectPluginPropertyExample();
			example.createCriteria().andProjectPluginIdEqualTo(id)
					.andIsDeletedEqualTo(HmCodeGenConstants.DATA_IS_VALID);
			List<ProjectPluginProperty> properties = projectPluginPropertyMapper.selectByExample(example);
			properties.forEach((item) -> {
				switch (item.getPropertyType()) {
				case 0:
					// 普通属性
					renderParams.put(item.getPropertyName(), item.getPropertyValue());
					break;
				case 1:
					// 密码属性
					String passText = "";
					if (StrUtil.isNotBlank(password.get(item.getPropertyName()))) {
						// 如果是传入参数，则解密
						passText = AESUtil.decrypt(password.get(item.getPropertyName()),
								HmCodeGenConstants.AES_PASSWORD_TRANS_KEY);
					} else {
						// 获取数据库值解密
						passText = AESUtil.decrypt(item.getPropertyValue(), HmCodeGenConstants.AES_PASSWORD_TRANS_KEY);
					}
					renderParams.put(item.getPropertyName(), passText);
				}
			});
			// 执行生成，并获取生成后的文件路径（全路径）
			String outputDir = excutor.codeGenerateExcuting(loginUser.getTraceId(), renderParams);

			// 返回生成路径
			return outputDir;
		}
		return "";
	}

	@Override
	public List<String> getFileList(String dir) {
		return FileUtil.listFileNames(dir);
	}

	@Override
	public String isDirectory(String dir) {
		// 读取文件
		File file = new File(dir);

		return file.isDirectory() ? "1" : "0";
	}

	@Override
	public List<ProjectPluginProperty> getProjectPluginProperties(Long id) {
		ProjectPluginPropertyExample example = new ProjectPluginPropertyExample();
		example.createCriteria().andProjectPluginIdEqualTo(id)
				.andIsDeletedEqualTo(HmCodeGenConstants.DATA_IS_VALID);
		List<ProjectPluginProperty> properties = projectPluginPropertyMapper.selectByExample(example);
		return properties;
	}

	@Override
	@Transactional
	public int saveProjectPluginProperties(Long id, List<ProjectPluginProperty> properties) {
		properties.forEach((item) -> {
			item.setProjectPluginId(id);
			if (item.getId() == null) {
				setPPRDefaultColumns(item, PersistEnum.insert);
				// 新增
				projectPluginPropertyMapper.insertSelective(item);
			} else {
				setPPRDefaultColumns(item, PersistEnum.update);
				// 更新
				projectPluginPropertyMapper.updateByPrimaryKeySelective(item);
			}
		});
		return 0;
	}

	@Override
	public byte[] downloadFile(String fileName) {
		return FileUtil.readBytes(fileName);
	}

	@Override
	public File downloadZip(String outpath) {
		return ZipUtil.zip(outpath);
	}
	
	/**
	 * 设置默认字段
	 * 
	 * @param record
	 * @param persisttype
	 */
	private void setDefaultColumns(ProjectPlugin record, PersistEnum persisttype) {
		Date now = new Date();
		// 获取登录信息
		HmteamAccount loginUser = RequestUtil.getAccountInfo();
		switch (persisttype) {
		case insert:
			record.setCreatedAt(now);
			record.setCreatedBy(loginUser.getUserName());
			record.setLastUpdatedBy(loginUser.getUserName());
			record.setLastUpdatedAt(now);
			record.setLastUpdatedTraceid(loginUser.getTraceId());
			record.setIsDeleted(HmCodeGenConstants.DATA_IS_VALID);
		case update:
			record.setLastUpdatedBy(loginUser.getUserName());
			record.setLastUpdatedAt(now);
			record.setLastUpdatedTraceid(loginUser.getTraceId());
		case delete:
			record.setLastUpdatedBy(loginUser.getUserName());
			record.setLastUpdatedAt(now);
			record.setLastUpdatedTraceid(loginUser.getTraceId());
			record.setIsDeleted(HmCodeGenConstants.DATA_IS_INVALID);
		}
	}
	
	/**
	 * 设置属性默认字段
	 * @param record
	 * @param persisttype
	 */
	private void setPPRDefaultColumns(ProjectPluginProperty record, PersistEnum persisttype) {
		Date now = new Date();
		// 获取登录信息
		HmteamAccount loginUser = RequestUtil.getAccountInfo();
		switch (persisttype) {
		case insert:
			record.setCreatedAt(now);
			record.setCreatedBy(loginUser.getUserName());
			record.setLastUpdatedBy(loginUser.getUserName());
			record.setLastUpdatedAt(now);
			record.setLastUpdatedTraceid(loginUser.getTraceId());
			record.setIsDeleted(HmCodeGenConstants.DATA_IS_VALID);
		case update:
			record.setLastUpdatedBy(loginUser.getUserName());
			record.setLastUpdatedAt(now);
			record.setLastUpdatedTraceid(loginUser.getTraceId());
		case delete:
			record.setLastUpdatedBy(loginUser.getUserName());
			record.setLastUpdatedAt(now);
			record.setLastUpdatedTraceid(loginUser.getTraceId());
			record.setIsDeleted(HmCodeGenConstants.DATA_IS_INVALID);
		}
	}

}
